﻿using System;
using System.Collections.Generic;
using System.Linq;
using Inscriptionem.Areas.Inscriptionem.Models.Requests;
using Inscriptionem.Authorization;
using Inscriptionem.Extensions;
using Inscriptionem.Models.Enums;
using Inscriptionem.Models.Requests;
using Inscriptionem.Models.Views;

namespace Inscriptionem.Services
{
    public static class LoginService
    {
        public static LoginError Login(string Mail, string Password)
        {
            string encryptedPassword = EncryptionService.EncryptString(Mail, Password);
            var db = new ORM.DB();
            var member = db.Members.FirstOrDefault(m => m.Mail == Mail.ToLower() && m.Password == encryptedPassword);

            if (member == null)
            {
                return LoginError.InvalidLoginPair;
            }

            // Login
            Member.Current.ID = member.ID;
            Member.Current.FirstName = member.FirstName;
            Member.Current.NickName = member.NickName;
            Member.Current.LastName = member.LastName;
            Member.Current.IsReadOnly = member.IsReadOnly || !member.IsRegistrationApproved;
            Member.Current.IsRealNameVisible = member.MemberSettings.IsRealNameVisible;

            foreach (var role in member.MemberRole)
            {
                if (Member.Current.Role == MemberRole.None)
                {
                    Member.Current.Role = (MemberRole) role.Role.ID;
                    continue;
                }

                Member.Current.Role |= (MemberRole) role.Role.ID;
            }

            return LoginError.None;
        }

        public static RegisterViewModel ValidateRegisterRequest(InstallRequestModel Model)
        {
            var result = new RegisterViewModel();

            // Apply model
            Model.CopyTo(result);

            if (string.IsNullOrWhiteSpace(result.FirstName))
            {
                result.Error = RegisterError.FirstNameEmpty;
            }
            else if (string.IsNullOrWhiteSpace(result.LastName))
            {
                result.Error = RegisterError.LastNameEmpty;
            }
            else if (string.IsNullOrWhiteSpace(result.Mail))
            {
                result.Error = RegisterError.MailEmpty;
            }
            else if (!result.Mail.Contains("@"))
            {
                result.Error = RegisterError.MailNotValid;
            }
            else if (string.IsNullOrWhiteSpace(result.MailConfirmation) || result.Mail != result.MailConfirmation)
            {
                result.Error = RegisterError.MailNotMatched;
            }
            else if (new ORM.DB().Members.Any(m => m.Mail == Model.Mail.ToLower()))
            {
                result.Error = RegisterError.MailNotAvailable;
            }
            else if (string.IsNullOrWhiteSpace(result.Password))
            {
                result.Error = RegisterError.PasswordEmpty;
            }
            else if (result.Password.Length < 6)
            {
                result.Error = RegisterError.PasswordLength;
            }
            else if (string.IsNullOrWhiteSpace(result.PasswordConfirmation) || result.Password != result.PasswordConfirmation)
            {
                result.Error = RegisterError.PasswordNotMatched;
            }

            return result;
        }

        public static bool Register(InstallRequestModel Model)
        {
            var db = new ORM.DB();
            DateTime date = DateTime.Now;

            // Add member
            var member = new ORM.Member()
            {
                FirstName = Model.FirstName,
                NickName = string.IsNullOrWhiteSpace(Model.NickName) ? string.Empty : Model.NickName,
                LastName = Model.LastName,
                Mail = Model.Mail.ToLower(),
                Password = EncryptionService.EncryptString(Model.Mail, Model.Password),
                BirthDate = DateTime.Now,
                CreatedDate = date,
                ModifiedDate = date,
                IsReadOnly = false,
                IsRegistrationApproved = !Configuration.Configuration.Instance.Members.RegistrationApprovalRequired
            };

            var memberSettings = new ORM.MemberSettings()
            {
                Description = string.Empty,
                IsMailVisible = Model.IsMailVisible,
                IsBirthDateVisible = Model.IsBirthDateVisible,
                IsRealNameVisible = Model.IsRealNameVisible,
                SiteLink = string.Empty,
                CreatedDate = date,
                ModifiedDate = date
            };

            member.MemberSettings = memberSettings;

            var memberRole = new ORM.MemberRole() { Role = db.Roles.First(r => r.ID == (int)MemberRole.Member) };
            member.MemberRole.Add(memberRole);

            db.AddToMembers(member);
            db.AddToMemberSettings(memberSettings);
            db.AddToMemberRoles(memberRole);

            db.SaveChanges();
            return true;
        }

        public static void ChangePassword(string Mail, string Password)
        {
            string encryptedPassword = EncryptionService.EncryptString(Mail, Password);
            var db = new ORM.DB();
            var member = db.Members.FirstOrDefault(m => m.Mail == Mail.ToLower());

            member.Password = encryptedPassword;
            member.ModifiedDate = DateTime.Now;

            db.SaveChanges();
        }

        public static bool Register(MemberAddRequestModel Model)
        {
            var db = new ORM.DB();
            DateTime date = DateTime.Now;

            // Add member
            var member = new ORM.Member()
            {
                FirstName = Model.FirstName,
                NickName = string.IsNullOrWhiteSpace(Model.NickName) ? string.Empty : Model.NickName,
                LastName = Model.LastName,
                Mail = Model.Mail.ToLower(),
                Password = EncryptionService.EncryptString(Model.Mail, Model.Password),
                BirthDate = Model.BirthDate,
                CreatedDate = date,
                ModifiedDate = date,
                IsReadOnly = Model.IsReadOnly,
                IsRegistrationApproved = Model.IsRegistrationApproved
            };

            var memberSettings = new ORM.MemberSettings()
            {
                Description = string.Empty,
                IsMailVisible = false,
                IsBirthDateVisible = true,
                SiteLink = string.Empty,
                CreatedDate = date,
                ModifiedDate = date
            };

            member.MemberSettings = memberSettings;

            db.AddToMembers(member);
            db.AddToMemberSettings(memberSettings);

            // Roles
            if (Model.Roles == null || Model.Roles.Count == 0)
            {
                Model.Roles = new List<MemberRoleRequestModel>()
                                  {
                                      new MemberRoleRequestModel()
                                          {
                                              ID = (int) MemberRole.Member,
                                              Enabled = true
                                          }
                                  };
            }

            foreach (var role in Model.Roles)
            {
                if (role.Enabled)
                {
                    var memberRole = new ORM.MemberRole() {Role = db.Roles.First(r => r.ID == role.ID)};
                    member.MemberRole.Add(memberRole);
                    db.AddToMemberRoles(memberRole);
                }
            }

            db.SaveChanges();
            return true;
        }
    }
}